package com.jeasonzhao.report.engine.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jeasonzhao.commons.utils.Algorithms;
import com.jeasonzhao.report.engine.Configuration;
import com.jeasonzhao.report.engine.ReportAgent;
import com.jeasonzhao.report.engine.ReportUserInfo;
import com.jeasonzhao.report.engine.impl.BasicHtmlRender;
import com.jeasonzhao.report.engine.impl.VisiFireRender;
import com.jeasonzhao.report.engine.irp.IChartRender;
import com.jeasonzhao.report.engine.irp.IReportRender;
import com.jeasonzhao.report.engine.irp.IUserProvider;
import com.jeasonzhao.report.engine.repo.ReportRepository;
import com.jeasonzhao.report.exceptions.ReportRuntimeException;
import com.jeasonzhao.report.model.Report;
import com.jeasonzhao.web.ServletHelper;
import com.jeasonzhao.report.exceptions.SQLReportException;
import com.jeasonzhao.report.exceptions.ReportParameterException;
import com.jeasonzhao.report.exceptions.*;
import com.jeasonzhao.web.IHtmlWriter;

public class ReportServletAgent
{
    private HttpServletRequest request;
//    private HttpServletResponse response = null;
    private String reportId = null;
    private ReportUserInfo currentUser = null;
    private IUserProvider userProvider = null;
    private Report report = null;
    public ReportServletAgent(HttpServletRequest req
                              ,HttpServletResponse resp
                              ,String report)
    {
        this.request = req;
//        this.response = resp;
        this.reportId = report;
    }

    public String execute()
    {

        java.util.Enumeration<String> er = request.getParameterNames();
        while(er.hasMoreElements())
        {
            String strTag = er.nextElement();
            System.out.println(request.getParameter(strTag));
        }
        System.out.println("================================================================");
        ServletParameterCollector parameterCollectors = new ServletParameterCollector(this.request);
        IHtmlWriter.StringWriter sw = new IHtmlWriter.StringWriter();
        IChartRender chartRender = new VisiFireRender();
        IReportRender render = new BasicHtmlRender(sw,chartRender);

        this.prepareContext();
        this.currentUser = this.prepareUser(this.userProvider);
        this.reportId = this.prepareReportId();

        try
        {
            checkReportExistance();
            verifyReportAccess(report);

            if(parameterCollectors.collectParameters(report,this.currentUser) == false)
            {
                render.renderParamterSelector(null,report,null);
            }
            ReportAgent agent = new ReportAgent(this.currentUser
                                                ,report
                                                ,parameterCollectors
                                                ,render,null);
            agent.processReport(parameterCollectors.getPageSize(report)
                                ,parameterCollectors.getPageNo(report));
        }
        catch(RenderException ex)
        {
            render.renderException(null,report,ex);
        }
        catch(ReportParameterException ex)
        {
            try
            {
                render.renderParamterSelector(null,report,ex);
            }
            catch(RenderException ex1)
            {
                render.renderException(null,report,ex1);
            }
        }
        catch(ReportServletException ex)
        {
            render.renderException(null,report,ex);
        }
        catch(SQLReportException ex)
        {
            render.renderException(null,report,ex);
        }
        return sw.toString();
    }

    private void checkReportExistance()
        throws ReportServletException
    {
        if(Algorithms.isEmpty(this.reportId))
        {
            throw new ReportServletException.NoReportID();
        }
        this.report = ReportRepository.getInstance().get(this.reportId);
        if(null == report)
        {
            throw new ReportServletException.NoReport(this.reportId);
        }
    }

    public Report getReport()
    {
        return this.report;
    }

    private void verifyReportAccess(Report report)
        throws ReportServletException
    {
        if(null==report)
        {
            return;
        }
        //Private report
        if(report.isPrivateReport()
           && report.getOwner() != null
           && (null == this.currentUser || report.getOwner().equals(this.currentUser.getId()) == false)
            )
        {
            throw new ReportServletException.NoPrivateReportAcess(report);
        }
        //Anonymous access
        if(null == this.currentUser)
        {
            if(false==Configuration.getInstance().isAnonymousAccess())
            {
                throw new ReportServletException.NoAnonymousAccess(report);
            }
            else if(null!=userProvider && false == userProvider.isAccessable(currentUser,report))
            {
                throw new ReportServletException.NoPriviledgeAccess(report);
            }
        }
    }

    protected void prepareContext()
    {
        this.userProvider = Configuration.getInstance().getUserProvider();
    }

    protected ReportUserInfo prepareUser(IUserProvider provider)
    {
        return null == provider ? null : provider.getCurrentUser(this.request);
    }

    public static Report getReport(javax.servlet.http.HttpServletRequest request,String rid)
        throws ReportRuntimeException
    {
        ServletParameterCollector parameterCollectors = new ServletParameterCollector(request);
        Report report = parameterCollectors.setupReport();
        if(null == report)
        {
            if(Algorithms.isEmpty(rid))
            {
                rid = ServletHelper.getParameter(request,Constants.REPORTID
                                                 ,"rptid","rpt","report");
            }
            if(Algorithms.notEmpty(rid))
            {
                return ReportRepository.getInstance().get(rid);
            }
        }
        return null;
    }
    protected String prepareReportId()
    {
        if(Algorithms.isEmpty(this.reportId))
        {
            this.reportId = ServletHelper.getParameter(request,Constants.REPORTID
                ,"rptid","rpt","report");
        }
        return this.reportId;
    }
}
